// Copyright DustedPixels.com 2008. All rights reserved.

package com.dustedpixels.jasmin.unit.compiler;

import java.util.regex.MatchResult;
import java.util.regex.Pattern;

/**
 * @author micapolos@gmail.com (Michal Pociecha-Los)
 */
public final class Regex {
  public final static Pattern PACKAGE_PATTERN =
    Pattern.compile("\\s*package\\s+(\\S+)\\s*;\\s*");
  
  public final static int PACKAGE_NAME_GROUP = 1;
  
  public final static Pattern IMPORT_PATTERN =
    Pattern.compile("\\s*import\\s+(\\S+)\\s*;\\s*");
  
  public final static int IMPORT_NAME_GROUP = 1;
  
  public final static Pattern UNIT_CLASS_DECLARATION_PATTERN = 
    Pattern.compile("\\s*(public|private)\\s(\\w+\\s+)*(\\w+)\\s+implements\\s+Unit\\s*\\{*");
  public final static int UNIT_CLASS_DECLARATION_NAME_GROUP = 3;
  
  public final static Pattern FIELD_DECLARATION_PATTERN = 
    Pattern.compile("\\s*((public|private)\\s(\\w+\\s+)*((\\w+)\\s*(\\[\\])*)\\s+(\\w+)\\s*(=\\s*(\\S+))?\\s*;\\s*)");
  public final static int FIELD_DECLARATION_UNINTENDED_GROUP = 1;
  public final static int FIELD_DECLARATION_ACCESS_GROUP = 2;
  public final static int FIELD_DECLARATION_TYPE_GROUP = 4;
  public final static int FIELD_DECLARATION_NAME_GROUP = 7;
  public final static int FIELD_DECLARATION_VALUE_GROUP = 9;
  
  public final static Pattern METHOD_DECLARATION_PATTERN =
    Pattern.compile("(\\s*)(public|private)\\s+(\\w+\\s+)+(\\w+)\\s*\\((.*)\\).*");
  public final static int METHOD_DECLARATION_INDENT_GROUP = 1;
  public final static int METHOD_DECLARATION_NAME_GROUP = 4;
  
  public final static Pattern CONSTRUCTOR_DECLARATION_PATTERN =
    Pattern.compile("(\\s*)(public|private)\\s+(\\w+)\\s*\\((.*)\\).*");
  public final static int CONSTRUCTOR_DECLARATION_INDENT_GROUP = 1;
  public final static int CONSTRUCTUR_DECLARATION_ARGS_GROUP = 4;
  
  public final static Pattern UNIT_FIELD_ACCESS_PATTERN =
      Pattern.compile("\\b(\\w+)(\\s*\\.\\s*)(\\w+)\\b");
  public final static int UNIT_FIELD_ACCESS_UNIT_NAME_GROUP = 1;
  public final static int UNIT_FIELD_ACCESS_DOT_GROUP = 2;
  public final static int UNIT_FIELD_ACCESS_FIELD_NAME_GROUP = 3;
  public static Pattern getUnitFieldAccessPattern(String unitName) {
    return Pattern.compile("\\b(\\Q" + unitName + "\\E)(\\s*\\.\\s*)(\\w+)\\b");
  }
  
  public static Pattern getFieldAccessPattern(String fieldName) {
    return Pattern.compile("\\b(\\Q" + fieldName + "\\E)\\b");
  }
  public static Pattern getThisFieldAccessPattern(String fieldName) {
    return Pattern.compile("this\\s*.\\s*(\\Q" + fieldName + "\\E)\\b");
  }
  
  
  public final static Pattern METHOD_ARGUMENT_PATTERN = 
    Pattern.compile("\\s*(\\w+\\s+)*(\\w+)\\s*");
  
  // Matches line with UnitTemplate instantiation.
  public final static Pattern CONSTRUCTOR_CALL_LINE_PATTERN = 
    Pattern.compile("\\s*(this\\s*\\.\\s*)?(\\w+)\\s*=\\s*new\\s+(\\w+)\\((.*)\\)\\s*;\\s*");
  public final static int CONSTRUCTOR_CALL_LINE_TARGET_GROUP = 2; 
  public final static int CONSTRUCTOR_CALL_LINE_CLASS_NAME_GROUP = 3;
  public final static int CONSTRUCTOR_CALL_LINE_PARAMETERS_GROUP = 4;  
  
  public final static int VARIABLE_NAME_GROUP = 1;
  public final static int FIELD_NAME_GROUP = 1;
  public final static int METHOD_NAME_GROUP = 1;
  
  public final static Pattern UPDATE_END_POINTS_CALL_LINE_PATTERN = 
      Pattern.compile("\\s*(\\w+)\\s*\\.\\s*updateEndPoints\\s*\\(\\s*\\)\\s*;\\s*");
  public final static int UPDATE_END_POINTS_CALL_LINE_TARGET_GROUP = 1;

  // Unit.update() method matching
  public final static Pattern UNIT_UPDATE_END_POINTS_METHOD_PATTERN =
      Pattern.compile("(\\s*)public\\s+void\\s+updateEndPoints\\s*\\(.*\\)\\s*\\{.*");
  public final static int UNIT_UPDATE_METHOD_INDENT_GROUP = 1;
  public static boolean matchesUnitUpdateMethodEnd(MatchResult methodMatcherResult, String line) {
    return line.startsWith(methodMatcherResult.group(UNIT_UPDATE_METHOD_INDENT_GROUP) + "}");
  }
  
  public static boolean isFieldDeclaredPublic(MatchResult matchResult) {
    return matchResult.group(1).equals("public");
  }

  public static String getDeclaredFieldName(MatchResult matchResult) {
    return matchResult.group(3);
  }

  public static String processDeclaredFieldName(MatchResult matchResult, 
      String accessModifier, String fieldName) {
    return matchResult.group().substring(0, matchResult.start(1)) +
        accessModifier +
        matchResult.group().substring(matchResult.end(1), matchResult.start(3)) +
        fieldName + 
        matchResult.group().substring(matchResult.start(3));
  }

  public static boolean isMethodPublic(MatchResult matchResult) {
    return matchResult.group(2).equals("public");
  }

  public static String getMethodName(MatchResult matchResult) {
    return matchResult.group(4);
  }

  public static boolean matchesEndOfMethod(MatchResult matchResult, String line) {
    return line.startsWith(matchResult.group(1) + "}");
  }

  public static String processMethodHeader(MatchResult matchResult, 
      String accessModifier, String methodName) {
    return matchResult.group().substring(0, matchResult.start(2)) +
        accessModifier +
        matchResult.group().substring(matchResult.end(2), matchResult.start(4)) +
        methodName + 
        matchResult.group().substring(matchResult.start(4));
  }
  
  public static Pattern getVariableNamePattern(String name) {
    return Pattern.compile("[^\\.]\\b(\\Q" + name + "\\E)\\b");
  }

  public static Pattern getFieldNamePattern(String name) {
    return Pattern.compile("\\b(\\Q" + name + "\\E)\\b");
  }

  public static Pattern getMethodNamePattern(String name) {
    return Pattern.compile("\\b(\\Q" + name + "\\E)\\s*\\(");
  }
}
